package org.eclipse.gittab.ui.handlers;

import java.util.List;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.expressions.EvaluationContext;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.gittab.gitTabDsl.TabModel;
import org.eclipse.gittab.player.GitTabPlayer;
import org.eclipse.gittab.player.GitTabPlayerFactory;
import org.eclipse.gittab.player.Player.PlayerListener;
import org.eclipse.gittab.ui.views.FretboardView;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.handlers.HandlerUtil;
import org.eclipse.xtext.concurrent.IUnitOfWork;
import org.eclipse.xtext.ui.common.editor.outline.ContentOutlineNode;

public class PlayHandler extends AbstractHandler {

	private final class PlayUnitOfWork implements IUnitOfWork<Object, EObject> {

		private final PlayerListener listener;

		/**
		 * 
		 * @param listener
		 *            may be <code>null</code> if no listener shall be
		 *            registered
		 */
		public PlayUnitOfWork(PlayerListener listener) {
			this.listener = listener;
		}

		@Override
		public Object exec(EObject state) throws Exception {

			if (state instanceof TabModel) {

				final TabModel tabModel = (TabModel) state;
				if (tabModel.getTab() != null) {
					GitTabPlayer tabPlayer = GitTabPlayerFactory
							.createComposerFor(tabModel);

					if (listener != null) {
						tabPlayer.getPlayer().addPlayerListener(listener);
					}

					tabPlayer.load(tabModel.getTab());

					tabPlayer.getPlayer().tempo(tabModel.getTab().getTempo());

					tabPlayer.getPlayer().play();

					if (listener != null) {
						// tabPlayer.getPlayer().removePlayerListener(listener);
					}
				}
			}

			return null;
		}
	}

	public Object execute(ExecutionEvent event) throws ExecutionException {

		IWorkbenchPartReference ref = HandlerUtil.getActiveWorkbenchWindow(
				event).getActivePage().findViewReference(FretboardView.ID);

		PlayerListener playerListener = null;

		if (ref != null) {
			IWorkbenchPart part = ref.getPart(false);

			playerListener = (PlayerListener) part;
		}

		EvaluationContext ctx = (EvaluationContext) event
				.getApplicationContext();

		List<?> list = (List<?>) ctx.getDefaultVariable();
		Object object = list.get(0);

		if (object instanceof ContentOutlineNode) {

			ContentOutlineNode contentOutlineNode = (ContentOutlineNode) object;
			contentOutlineNode.getEObjectHandle().readOnly(
					new PlayUnitOfWork(playerListener));
		}

		return null;
	}
}
